// $codepro.audit.disable numericLiterals
/**
 * This file was created by Nick Popescu Taylor Garren for use in
 * SpaceTrader
 */

/**
 * This file was created by Nick Popescu and Taylor Garren for use in
 * SpaceTrader
 */

import java.io.Serializable;

/**
 * This class represents a spaceship and all of its underlying properties.
 * 
 * @author Nick Popescu, Taylor Garren
 * @version 1.0
 */
public class Ship implements Serializable {
    
    /**
     * The array of items in the ship
     */
    
    private final Resource[] cargo;

    /**
     * The name of the ship
     */
    
    private final String thisName;
    
    /**
     * The ship's capacity
     */
    
    private int thisCapacity;
    
    /**
     * The ship's number of weapon slots
     */
    
    private final int thisWeaponSlots;
    
    /**
     * The ship's number of shield slots
     */
    
    private final int thisShieldSlots;
    
    /**
     * The ship's number of gadget slots
     */
    
    private final int thisGadgetSlots;
    
    /**
     * The ship's crew size
     */
    
    private final int thisCrewSize;
    
    /**
     * The ship's fuel capacity
     */
    
    private final int thisFuelSize;
    
    /**
     * The ship's minimum tech level
     */
    
    private final int thisMinTechLevel;
    
    /**
     * The ship's fuel cost
     */
    
    private final int thisFuelCost;
    
    /**
     * The ship's price
     */
    
    private final int thisPrice;
    
    /**
     * The ship's bounty
     */
    
    private final int thisBounty;
    // skipping occurance
    
    /**
     * The ship's hull strength
     */
    
    private final int thisHullStrength;
    // skipping police, pirates, and traders.
    
    /**
     * The ship's repair cost
     */
    
    private final int thisRepairCost;
    
    /**
     * The ship's size
     */
    
    private final int thisSize;

    // Taylor Garren add:
    /**
     * The total number of items in the ship
     */
    
    private int totalCargo;
    
    /**
     * The total amount of fuel in the ship
     */
    
    private int currFuelLevel;

    /*
     * These are all of the variables that the ships can have. They are
     * structured into arrays because a given ship is assigned an Integer value,
     * and this integer value is the index from which all of the data will be
     * pulled.
     */
    /**
     * All ship names
     */
    
    private final String[] names = new String[] { "Flea", "Gnat", "Firefly",
	    "Mosquito", "BumbleBee" };
    
    /**
     * All ships' capacity sizes
     */
    
    private final int[] capacitySizes = new int[] { 10, 15, 20, 15, 25 };
    
    /**
     * All ships' weapon slots
     */
    
    private final int[] weaponSlots = new int[] { 0, 1, 1, 2, 1 };
    
    /**
     * All ships' shield slots
     */
    
    private final int[] shieldSlots = new int[] { 0, 0, 1, 1, 2 };
    
    /**
     * All ships' gadget slots
     */
    
    private final int[] gadgetSlots = new int[] { 0, 1, 1, 1, 2 };
    
    /**
     * All ships' crew sizes
     */
    
    private final int[] crewSizes = new int[] { 1, 1, 1, 1, 2 };
    
    /**
     * All ships' fuel sizes
     */
    
    private final int[] fuelSizes = new int[] { 20, 14, 17, 13, 15 };
    
    /**
     * All ships' minimum tech level
     */
    
    private final int[] minTechLevel = new int[] { 4, 5, 5, 5, 5 };
    
    /**
     * All ships' fuel costs
     */
    
    private final int[] fuelCost = new int[] { 1, 2, 3, 5, 7 };
    
    /**
     * All ships' prices
     */
    
    private final int[] price = new int[] { 2000, 10000, 25000, 30000, 60000 };
    
    /**
     * All ships' bounties
     */
    
    private final int[] bounty = new int[] { 5, 50, 75, 100, 125 };
    
    /**
     * All ships' hull strengths
     */
    
    private final int[] hullStrength = new int[] { 25, 100, 100, 100, 100 };
    
    /**
     * All ships' repair costs
     */
    
    private final int[] repairCost = new int[] { 1, 1, 1, 1, 1 };
    
    /**
     * All ships' sizes
     */
    
    private final int[] size = new int[] { 0, 1, 1, 1, 2 };

    /**
     * Generates a ship based on the passed-in name. Once the name is converted
     * to a number, this number is used to assign this ship all of its
     * applicable variable values. This is done so that it is easy to story all
     * of the default stats in arrays and to just index into them based on the
     * name.
     * 
     * @param name
     *            The name of the ship, which is used to assign the ship its
     *            stats.
     */
    public Ship(String name) {
	int shipType = convertToType(name); // converts the name of the ship to
					    // an integer.
	if (shipType == -1) {// If the name is invalid, then make a Gnat ship.
	    // do nothing; ship type doesn't exist.

	    System.out.println("COULDN'T FIND SHIP!");
	    shipType = 1;// Making a Gnat

	}
	this.thisName = names[shipType];
	this.thisCapacity = capacitySizes[shipType];
	this.thisCapacity = capacitySizes[shipType];
	this.thisWeaponSlots = weaponSlots[shipType];
	this.thisShieldSlots = shieldSlots[shipType];
	this.thisGadgetSlots = gadgetSlots[shipType];
	this.thisCrewSize = crewSizes[shipType];
	this.thisFuelSize = fuelSizes[shipType];
	this.currFuelLevel = fuelSizes[shipType];
	this.thisMinTechLevel = minTechLevel[shipType];
	this.thisFuelCost = fuelCost[shipType];
	this.thisPrice = price[shipType];
	this.thisBounty = bounty[shipType];
	this.thisHullStrength = hullStrength[shipType];
	this.thisRepairCost = repairCost[shipType];
	this.thisSize = size[shipType];

	this.cargo = new Resource[10];
	establishCargoHold();
	totalCargo = 0;
    }

    /**
     * Converts the given String name of the ship to its associated integer
     * representation.
     * 
     * @param name
     *            The name of the ship, in String form, which will be converted.
     * @return Integer representation of the ship.
     */
    protected final int convertToType(String name) {
	for (int i = 0; i < names.length; i++) {// Go through the array of the
						// names
	    if (names[i].equals(name)) {// If the passed-in name is in the array
		return i;// Then return the associated ship number.
	    }
	}
	return -1; // if the passed-in ship type doesn't exist.
    }

    /**
     * Used to get the name of this ship.
     * 
     * @return The name of this ship.
     */
    public String getName() {
	return thisName;
    }

    /**
     * Sets up the ship's cargo hold. Creates an array of resources, whose
     * multiplicity is set to 0 to show that they are not actually available on
     * the ship.
     */
    public final void establishCargoHold() {
	for (int i = 0; i < cargo.length; i++) {
	    cargo[i] = new Resource(i);
	}
    }

    /**
     * Checks if more items can be added to the ship based on its capacity.
     * 
     * @param numItemsToAdd
     *            How many more items will be added.
     * @return True if items can be added, false otherwise.
     */
    public boolean canAddItem(int numItemsToAdd) {
	if (totalCargo + numItemsToAdd > thisCapacity) {
	    return false;
	}
	return true;
    }

    /**
     * Adds the given resource amount to the ship.
     * 
     * @param resourceIndex
     *            The index of the resource that is being added.
     * @param numItems
     *            The number of the given resource to add.
     */
    public void addItem(int resourceIndex, int numItems) {
	cargo[resourceIndex].setMultiplicity(cargo[resourceIndex]
		.getMultiplicity() + numItems);
	totalCargo += numItems;
    }

    /**
     * Checks if the given amount of a resource can be removed from the ship.
     * 
     * @param numItemsToRemove
     *            How many of a given item should be removed.
     * @return True if the items can be removed, false otherwise.
     */
    public boolean canRemoveItem(int numItemsToRemove) {
	if (totalCargo - numItemsToRemove < 0) {
	    return false;
	}
	return true;
    }

    /**
     * Removes the given amount of a given resource from the ship.
     * 
     * @param resourceIndex
     *            The index of the resource to be removed.
     * @param numItems
     *            The amount of a given resource to remove.
     */
    public void removeItem(int resourceIndex, int numItems) {
	cargo[resourceIndex].setMultiplicity(cargo[resourceIndex]
		.getMultiplicity() - numItems);
	totalCargo -= numItems;
    }

    /**
     * Used to get an array of all the resources, and their multiplicities, on
     * the ship.
     * 
     * @return An array of all the resources on the ship and their associated
     *         multiplicities.
     */
    public Resource[] getCargo() {
	return cargo;
    }

    /**
     * Checks to see if the player can add the amount of fuel to their ship
     * specified by the parameter. Returns true if the player can and false if
     * he/she can't
     * 
     * @param amountFuel
     *            The amount of fuel you're trying to add
     * @return True if the fuel can be added to the ship, false if the ship
     *         can't hold that much fuel
     */
    public boolean canAddFuel(int amountFuel) {
	if (currFuelLevel + amountFuel <= thisFuelSize) {
	    return true;
	}
	return false;
    }

    /**
     * Adds the specified amount of fuel to the ship
     * 
     * @param amountFuel
     *            The amoung of fuel to add to the ship
     */
    public void addFuel(int amountFuel) {
	if (canAddFuel(amountFuel)) {
	    currFuelLevel = currFuelLevel + amountFuel;
	}
    }

    /**
     * Checks to see whether the ship can has enough fuel to use up the amount
     * specified. The method returns false if the ship does not have that much
     * fuel to use, and true if it does
     * 
     * @param amountFuel
     *            The amount of fuel the player is trying to use
     * @return True if the player can use that fuel, and false if he/she cannot
     */
    public boolean canUseFuel(int amountFuel) {
	if (currFuelLevel - amountFuel >= 0) {
	    return true;
	}
	return false;
    }

    /**
     * Subtracts the amount specified from the ship's total amount of fuel (used
     * in travel)
     * 
     * @param amountFuel
     *            The amount of fuel to take away from the ship's current fuel
     *            level
     */
    public void useFuel(int amountFuel) {
	if (canUseFuel(amountFuel)) {
	    currFuelLevel = currFuelLevel - amountFuel;
	}
    }

    /**
     * Returns the current amount of fuel in the ship
     * 
     * @return the current amount of fuel in the ship
     */
    public int getCurrFuelLevel() {
	return currFuelLevel;
    }

    /**
     * Used to get the maximum fuel capacity of the given ship.
     * 
     * @return The maximum fuel copacity of this ship.
     */
    public int getThisFuelSize() {
	return thisFuelSize;
    }

    /**
     * Used to get the total cargo of the ship.
     * 
     * @return The total cargo of the ship.
     */
    public int getTotalCargo() {
	return totalCargo;
    }

    /**
     * Sets the total cargo to the given number
     * @param num The number to which the count of total cargo should be set
     */
    public void setTotalCargo(int num) {
	this.totalCargo = num;
    }

    /**
     * Used to get the capacity of the ship.
     * 
     * @return The capacity of the ship.
     */
    public int getThisCapacity() {
	return thisCapacity;
    }

    /**
     * @return The fuel size of the ship
     */
    public int thisFuelSize() {
	return thisFuelSize;
    }

    /**
     * @return The results of the default toString() method for a class
     */
    public String toString() {
	return this.toString();
    }

}
